<!doctype html>
<!--
    Cryptocurrency transaction monitoring thingy v0.1

    (c) 2015 by Robin Leffmann <djinn at stolendata dot net>

    https://github.com/stolendata/cctmt/

    licensed under CC BY-NC-SA 4.0 - http://creativecommons.org/licenses/by-nc-sa/4.0/
-->
<html lang="en">
<head>
<meta charset="utf-8" />
<link href="http://fonts.googleapis.com/css?family=Source+Code+Pro&amp;subset=latin,latin-ext" rel="stylesheet" type="text/css" />
<title>Cryptocurrency transaction monitoring thingy</title>
<style type="text/css">
html { background-image: linear-gradient( #202020, #303030 );
       width: 100%;
       height: 100%; }
body { color: #ffffff;
       margin: 16px;
       font-size: 14px;
       font-family: "Source Code Pro", monospace; }
a { color: #ffffff;
    text-decoration: none; }
a.du { border-bottom: 1px dotted; }
span.blob { color: #ffffff;
            font-size: 12px;
            display: inline-block;
            margin: 2px;
            padding: 4px 8px;
            border: 0; }
span.purple { border-radius: 4px; background-image: linear-gradient( #724ccb, #4823a1 ); }
span.blue { border-radius: 10px; background-image: linear-gradient( #4c72cb, #2348a1 ); }
span.green { border-radius: 4px; background-image: linear-gradient( #62ab3c, #389113 ); }
span.gold { border-radius: 10px; background-image: linear-gradient( #c8a020, #685010 ); }
span.gray { color: #808080; border-radius: 10px; background-image: linear-gradient( #404040, #202020 ); }
</style>
<script type="text/javascript">
var currency = { 'BTC' : {'symbol':'\u0243', // alt. \u0e3f
                          'ws':'wss://ws.blockchain.info/inv',
                          'eval_amount':'for( n in resp.x.out ) amount += resp.x.out[n].value;',
                          'tx_url':'https://blockchain.info/tx/',
                          'block_url':'https://blockchain.info/block/',
                          'sub_tx':'{"op":"unconfirmed_sub"}',
                          'sub_block':'{"op":"blocks_sub"}',
                          'sel_index':0},
                 'LTC' : {'symbol':'\u0141',
                          'ws':'ws://ws.ltcchain.com:8000',
                          'eval_amount':'for( n in resp.x.out ) amount += resp.x.out[n].value;',
                          'tx_url':'http://litechain.info/tx/',
                          'block_url':'http://litechain.info/block/',
                          'sub_tx':'{"op":"tx_sub"}',
                          'sub_block':'{"op":"block_sub"}',
                          'sel_index':1},
                 'DOGE' : {'symbol':'\u00d0',
                           'ws':'wss://ws.dogechain.info/inv',
                           'eval_amount':'amount = resp.x.value_out;',
                           'tx_url':'https://dogechain.info/tx/',
                           'block_url':'https://dogechain.info/block/',
                           'sub_tx':'{"op":"unconfirmed_sub"}',
                           'sub_block':'{"op":"blocks_sub"}',
                           'sel_index':2},
                 'EUR' : '&euro;',
                 'USD' : '$' };
var c;
var f = 'USD'; // fixed USD fiat for now, because chain.so doesn't relay any EUR rates yet

// the .fill prototype works in Safari and Firefox, but Chrome insists on being garbage...
var items = new Array( 15 );
for( var i = 0; i < items.length; i++ )
    items[i] = '<span class="blob">&nbsp;</span>';

var coin = 100000000;
var totmin = ws = to = null;

function get_rate()
{
    if( to != null )
    {
        clearTimeout( to );

        // update the past minute's total output
        document.getElementById( 'totmin' ).innerHTML = currency[f] + +totmin.toFixed( 1 );
    }

    totmin = 0;

    document.getElementById( 'exch' ).innerHTML = currency[c].symbol + '1 = ' + currency[f];

    var xml = new XMLHttpRequest();
    xml.open( 'GET', 'https://chain.so/api/v2/get_price/' + c + '/' + f, false );
    xml.send( null );
    if( xml.status == '200' )
        document.getElementById( 'rate' ).innerHTML = JSON.parse( xml.responseText ).data.prices[0].price;

    to = window.setTimeout( 'get_rate();', 1000 * 60 );
}

function render()
{
    items.pop();

    var out = '';
    for( var i = 0; i < items.length; i++ )
        out += ( items[i] ? items[i] : '' ) + '<br />';
    document.getElementById( 'tx' ).innerHTML = out;
}

function everything()
{
    if( ws != null )
        ws.close();

    if( c == null )
    {
        // clumsy, but once again that's how it goes with Chrome being garbage
        var i = location.search.substr( 1 ).toUpperCase();
        if( currency[i] != null && currency[i].sel_index != null )
            document.getElementById( 'currency' ).selectedIndex = currency[i].sel_index;
    }

    document.getElementById( 'status' ).innerHTML = 'Connecting&hellip;';
    document.getElementById( 'rate' ).innerHTML = '&hellip;';
    c = document.getElementById( 'currency' ).value;
    items.unshift( '<span class="blob green">Now monitoring ' + c + '</span>' );
    render();

    get_rate();

    ws = new WebSocket( currency[c].ws );
    document.getElementById( 'totmin' ).innerHTML = '&hellip;'

    ws.onopen = function()
    {
        document.getElementById( 'status' ).innerHTML = 'Connected!';
        ws.send( currency[c].sub_tx );
        ws.send( currency[c].sub_block );
    }

    ws.onmessage = function( r )
    {
//        console.log( r );
        var resp = JSON.parse( r.data );

        if( resp.op == 'status' )
            return;

        if( resp.op == 'block' )
            items.unshift( '<span class="blob green">' + c + ' <a class="du" href="' + currency[c].block_url + resp.x.hash + '" target="_blank">#' + resp.x.height + '</a></span>' );
        else if( resp.op == 'utx' )
        {
            // eval total output in the transaction
            var amount = 0;
            eval( currency[c].eval_amount );
            amount /= coin;

            // tx, ins->outs, amount
            items.unshift( '<span class="blob purple"><a class="du" href="' + currency[c].tx_url + resp.x.hash + '" target="_blank">' + resp.x.hash.substring( 0, 32 ) + '&hellip;</a></span> <span class="blob gray">' + resp.x.vin_sz + '\u2192' + resp.x.vout_sz + '</span> <span class="blob blue">' + currency[c].symbol + amount + '</span>' );

            // fiat value
            var rate = document.getElementById( 'rate' ).innerHTML;
            var fiat = amount * rate;
            totmin += fiat;
            items[0] += '<span class="blob gold">' + currency[f] + fiat.toFixed( fiat < 1 ? 5 : 2 ) + '</span>';
        }
        render();
    }
}
</script>
</head>
<body onload="everything();" onbeforeunload="ws.close();">
<span id="status"></span> <a href="javascript:everything();">&#10227;</a> &middot; <select id="currency" onchange="everything();"><option value="BTC">BTC</option><option value="LTC">LTC</option><option value="DOGE">DOGE</option></select> &middot; <span id="exch"></span><span id="rate"></span> &middot; Total output the past minute: <span id="totmin"></span><br /><br />
<span id="tx"></span><br />
<a class="du" href="https://github.com/stolendata/cctmt/">https://github.com/stolendata/cctmt/</a><br /><br />
BTC: 1EDhbo9ejdKUxNW3GPBh1UmocC1ea1TvE5<br />
LTC: LaDuRFwEt1V26pmJJH94auDvxqN3rRFqPj<br />
DOGE: DJ7vQ1dNRfebb1umVHsHxoMcd2Zq5L6LKp
</body>
</html>
